home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Tk / generic / tkCanvImg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-31  |  18.9 KB  |  678 lines

  1. /* 
  2.  * tkCanvImg.c --
  3.  *
  4.  *    This file implements image items for canvas widgets.
  5.  *
  6.  * Copyright (c) 1994 The Regents of the University of California.
  7.  * Copyright (c) 1994-1996 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * SCCS: @(#) tkCanvImg.c 1.17 96/02/17 17:18:43
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include "tkInt.h"
  17. #include "tkPort.h"
  18. #include "tkCanvas.h"
  19.  
  20. /*
  21.  * The structure below defines the record for each image item.
  22.  */
  23.  
  24. typedef struct ImageItem  {
  25.     Tk_Item header;        /* Generic stuff that's the same for all
  26.                  * types.  MUST BE FIRST IN STRUCTURE. */
  27.     Tk_Canvas canvas;        /* Canvas containing the image. */
  28.     double x, y;        /* Coordinates of positioning point for
  29.                  * image. */
  30.     Tk_Anchor anchor;        /* Where to anchor image relative to
  31.                  * (x,y). */
  32.     char *imageString;        /* String describing -image option (malloc-ed).
  33.                  * NULL means no image right now. */
  34.     Tk_Image image;        /* Image to display in window, or NULL if
  35.                  * no image at present. */
  36. } ImageItem;
  37.  
  38. /*
  39.  * Information used for parsing configuration specs:
  40.  */
  41.  
  42. static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
  43.     Tk_CanvasTagsPrintProc, (ClientData) NULL
  44. };
  45.  
  46. static Tk_ConfigSpec configSpecs[] = {
  47.     {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
  48.     "center", Tk_Offset(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
  49.     {TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL,
  50.     (char *) NULL, Tk_Offset(ImageItem, imageString), TK_CONFIG_NULL_OK},
  51.     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
  52.     (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
  53.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  54.     (char *) NULL, 0, 0}
  55. };
  56.  
  57. /*
  58.  * Prototypes for procedures defined in this file:
  59.  */
  60.  
  61. static void        ImageChangedProc _ANSI_ARGS_((ClientData clientData,
  62.                 int x, int y, int width, int height, int imgWidth,
  63.                 int imgHeight));
  64. static int        ImageCoords _ANSI_ARGS_((Tcl_Interp *interp,
  65.                 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
  66.                 char **argv));
  67. static int        ImageToArea _ANSI_ARGS_((Tk_Canvas canvas,
  68.                 Tk_Item *itemPtr, double *rectPtr));
  69. static double        ImageToPoint _ANSI_ARGS_((Tk_Canvas canvas,
  70.                 Tk_Item *itemPtr, double *coordPtr));
  71. static void        ComputeImageBbox _ANSI_ARGS_((Tk_Canvas canvas,
  72.                 ImageItem *imgPtr));
  73. static int        ConfigureImage _ANSI_ARGS_((Tcl_Interp *interp,
  74.                 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
  75.                 char **argv, int flags));
  76. static int        CreateImage _ANSI_ARGS_((Tcl_Interp *interp,
  77.                 Tk_Canvas canvas, struct Tk_Item *itemPtr,
  78.                 int argc, char **argv));
  79. static void        DeleteImage _ANSI_ARGS_((Tk_Canvas canvas,
  80.                 Tk_Item *itemPtr, Display *display));
  81. static void        DisplayImage _ANSI_ARGS_((Tk_Canvas canvas,
  82.                 Tk_Item *itemPtr, Display *display, Drawable dst,
  83.                 int x, int y, int width, int height));
  84. static void        ScaleImage _ANSI_ARGS_((Tk_Canvas canvas,
  85.                 Tk_Item *itemPtr, double originX, double originY,
  86.                 double scaleX, double scaleY));
  87. static void        TranslateImage _ANSI_ARGS_((Tk_Canvas canvas,
  88.                 Tk_Item *itemPtr, double deltaX, double deltaY));
  89.  
  90. /*
  91.  * The structures below defines the image item type in terms of
  92.  * procedures that can be invoked by generic item code.
  93.  */
  94.  
  95. Tk_ItemType tkImageType = {
  96.     "image",                /* name */
  97.     sizeof(ImageItem),            /* itemSize */
  98.     CreateImage,            /* createProc */
  99.     configSpecs,            /* configSpecs */
  100.     ConfigureImage,            /* configureProc */
  101.     ImageCoords,            /* coordProc */
  102.     DeleteImage,            /* deleteProc */
  103.     DisplayImage,            /* displayProc */
  104.     0,                    /* alwaysRedraw */
  105.     ImageToPoint,            /* pointProc */
  106.     ImageToArea,            /* areaProc */
  107.     (Tk_ItemPostscriptProc *) NULL,    /* postscriptProc */
  108.     ScaleImage,                /* scaleProc */
  109.     TranslateImage,            /* translateProc */
  110.     (Tk_ItemIndexProc *) NULL,        /* indexProc */
  111.     (Tk_ItemCursorProc *) NULL,        /* icursorProc */
  112.     (Tk_ItemSelectionProc *) NULL,    /* selectionProc */
  113.     (Tk_ItemInsertProc *) NULL,        /* insertProc */
  114.     (Tk_ItemDCharsProc *) NULL,        /* dTextProc */
  115.     (Tk_ItemType *) NULL        /* nextPtr */
  116. };
  117.  
  118. /*
  119.  *--------------------------------------------------------------
  120.  *
  121.  * CreateImage --
  122.  *
  123.  *    This procedure is invoked to create a new image
  124.  *    item in a canvas.
  125.  *
  126.  * Results:
  127.  *    A standard Tcl return value.  If an error occurred in
  128.  *    creating the item, then an error message is left in
  129.  *    interp->result;  in this case itemPtr is left uninitialized,
  130.  *    so it can be safely freed by the caller.
  131.  *
  132.  * Side effects:
  133.  *    A new image item is created.
  134.  *
  135.  *--------------------------------------------------------------
  136.  */
  137.  
  138. static int
  139. CreateImage(interp, canvas, itemPtr, argc, argv)
  140.     Tcl_Interp *interp;            /* Interpreter for error reporting. */
  141.     Tk_Canvas canvas;            /* Canvas to hold new item. */
  142.     Tk_Item *itemPtr;            /* Record to hold new item;  header
  143.                      * has been initialized by caller. */
  144.     int argc;                /* Number of arguments in argv. */
  145.     char **argv;            /* Arguments describing rectangle. */
  146. {
  147.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  148.  
  149.     if (argc < 2) {
  150.     Tcl_AppendResult(interp, "wrong # args: should be \"",
  151.         Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
  152.         itemPtr->typePtr->name, " x y ?options?\"",
  153.         (char *) NULL);
  154.     return TCL_ERROR;
  155.     }
  156.  
  157.     /*
  158.      * Initialize item's record.
  159.      */
  160.  
  161.     imgPtr->canvas = canvas;
  162.     imgPtr->anchor = TK_ANCHOR_CENTER;
  163.     imgPtr->imageString = NULL;
  164.     imgPtr->image = NULL;
  165.  
  166.     /*
  167.      * Process the arguments to fill in the item record.
  168.      */
  169.  
  170.     if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &imgPtr->x) != TCL_OK)
  171.         || (Tk_CanvasGetCoord(interp, canvas, argv[1], &imgPtr->y)
  172.         != TCL_OK)) {
  173.     return TCL_ERROR;
  174.     }
  175.  
  176.     if (ConfigureImage(interp, canvas, itemPtr, argc-2, argv+2, 0) != TCL_OK) {
  177.     DeleteImage(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
  178.     return TCL_ERROR;
  179.     }
  180.     return TCL_OK;
  181. }
  182.  
  183. /*
  184.  *--------------------------------------------------------------
  185.  *
  186.  * ImageCoords --
  187.  *
  188.  *    This procedure is invoked to process the "coords" widget
  189.  *    command on image items.  See the user documentation for
  190.  *    details on what it does.
  191.  *
  192.  * Results:
  193.  *    Returns TCL_OK or TCL_ERROR, and sets interp->result.
  194.  *
  195.  * Side effects:
  196.  *    The coordinates for the given item may be changed.
  197.  *
  198.  *--------------------------------------------------------------
  199.  */
  200.  
  201. static int
  202. ImageCoords(interp, canvas, itemPtr, argc, argv)
  203.     Tcl_Interp *interp;            /* Used for error reporting. */
  204.     Tk_Canvas canvas;            /* Canvas containing item. */
  205.     Tk_Item *itemPtr;            /* Item whose coordinates are to be
  206.                      * read or modified. */
  207.     int argc;                /* Number of coordinates supplied in
  208.                      * argv. */
  209.     char **argv;            /* Array of coordinates: x1, y1,
  210.                      * x2, y2, ... */
  211. {
  212.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  213.     char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
  214.  
  215.     if (argc == 0) {
  216.     Tcl_PrintDouble(interp, imgPtr->x, x);
  217.     Tcl_PrintDouble(interp, imgPtr->y, y);
  218.     Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
  219.     } else if (argc == 2) {
  220.     if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &imgPtr->x) != TCL_OK)
  221.         || (Tk_CanvasGetCoord(interp, canvas, argv[1],
  222.             &imgPtr->y) != TCL_OK)) {
  223.         return TCL_ERROR;
  224.     }
  225.     ComputeImageBbox(canvas, imgPtr);
  226.     } else {
  227.     sprintf(interp->result,
  228.         "wrong # coordinates: expected 0 or 2, got %d", argc);
  229.     return TCL_ERROR;
  230.     }
  231.     return TCL_OK;
  232. }
  233.  
  234. /*
  235.  *--------------------------------------------------------------
  236.  *
  237.  * ConfigureImage --
  238.  *
  239.  *    This procedure is invoked to configure various aspects
  240.  *    of an image item, such as its anchor position.
  241.  *
  242.  * Results:
  243.  *    A standard Tcl result code.  If an error occurs, then
  244.  *    an error message is left in interp->result.
  245.  *
  246.  * Side effects:
  247.  *    Configuration information may be set for itemPtr.
  248.  *
  249.  *--------------------------------------------------------------
  250.  */
  251.  
  252. static int
  253. ConfigureImage(interp, canvas, itemPtr, argc, argv, flags)
  254.     Tcl_Interp *interp;        /* Used for error reporting. */
  255.     Tk_Canvas canvas;        /* Canvas containing itemPtr. */
  256.     Tk_Item *itemPtr;        /* Image item to reconfigure. */
  257.     int argc;            /* Number of elements in argv.  */
  258.     char **argv;        /* Arguments describing things to configure. */
  259.     int flags;            /* Flags to pass to Tk_ConfigureWidget. */
  260. {
  261.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  262.     Tk_Window tkwin;
  263.     Tk_Image image;
  264.  
  265.     tkwin = Tk_CanvasTkwin(canvas);
  266.     if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc,
  267.         argv, (char *) imgPtr, flags) != TCL_OK) {
  268.     return TCL_ERROR;
  269.     }
  270.  
  271.     /*
  272.      * Create the image.  Save the old image around and don't free it
  273.      * until after the new one is allocated.  This keeps the reference
  274.      * count from going to zero so the image doesn't have to be recreated
  275.      * if it hasn't changed.
  276.      */
  277.  
  278.     if (imgPtr->imageString != NULL) {
  279.     image = Tk_GetImage(interp, tkwin, imgPtr->imageString,
  280.         ImageChangedProc, (ClientData) imgPtr);
  281.     if (image == NULL) {
  282.         return TCL_ERROR;
  283.     }
  284.     } else {
  285.     image = NULL;
  286.     }
  287.     if (imgPtr->image != NULL) {
  288.     Tk_FreeImage(imgPtr->image);
  289.     }
  290.     imgPtr->image = image;
  291.     ComputeImageBbox(canvas, imgPtr);
  292.     return TCL_OK;
  293. }
  294.  
  295. /*
  296.  *--------------------------------------------------------------
  297.  *
  298.  * DeleteImage --
  299.  *
  300.  *    This procedure is called to clean up the data structure
  301.  *    associated with a image item.
  302.  *
  303.  * Results:
  304.  *    None.
  305.  *
  306.  * Side effects:
  307.  *    Resources associated with itemPtr are released.
  308.  *
  309.  *--------------------------------------------------------------
  310.  */
  311.  
  312. static void
  313. DeleteImage(canvas, itemPtr, display)
  314.     Tk_Canvas canvas;            /* Info about overall canvas widget. */
  315.     Tk_Item *itemPtr;            /* Item that is being deleted. */
  316.     Display *display;            /* Display containing window for
  317.                      * canvas. */
  318. {
  319.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  320.  
  321.     if (imgPtr->imageString != NULL) {
  322.     ckfree(imgPtr->imageString);
  323.     }
  324.     if (imgPtr->image != NULL) {
  325.     Tk_FreeImage(imgPtr->image);
  326.     }
  327. }
  328.  
  329. /*
  330.  *--------------------------------------------------------------
  331.  *
  332.  * ComputeImageBbox --
  333.  *
  334.  *    This procedure is invoked to compute the bounding box of
  335.  *    all the pixels that may be drawn as part of a image item.
  336.  *    This procedure is where the child image's placement is
  337.  *    computed.
  338.  *
  339.  * Results:
  340.  *    None.
  341.  *
  342.  * Side effects:
  343.  *    The fields x1, y1, x2, and y2 are updated in the header
  344.  *    for itemPtr.
  345.  *
  346.  *--------------------------------------------------------------
  347.  */
  348.  
  349.     /* ARGSUSED */
  350. static void
  351. ComputeImageBbox(canvas, imgPtr)
  352.     Tk_Canvas canvas;            /* Canvas that contains item. */
  353.     ImageItem *imgPtr;            /* Item whose bbox is to be
  354.                      * recomputed. */
  355. {
  356.     int width, height;
  357.     int x, y;
  358.  
  359.     x = imgPtr->x + ((imgPtr->x >= 0) ? 0.5 : - 0.5);
  360.     y = imgPtr->y + ((imgPtr->y >= 0) ? 0.5 : - 0.5);
  361.  
  362.     if (imgPtr->image == None) {
  363.     imgPtr->header.x1 = imgPtr->header.x2 = x;
  364.     imgPtr->header.y1 = imgPtr->header.y2 = y;
  365.     return;
  366.     }
  367.  
  368.     /*
  369.      * Compute location and size of image, using anchor information.
  370.      */
  371.  
  372.     Tk_SizeOfImage(imgPtr->image, &width, &height);
  373.     switch (imgPtr->anchor) {
  374.     case TK_ANCHOR_N:
  375.         x -= width/2;
  376.         break;
  377.     case TK_ANCHOR_NE:
  378.         x -= width;
  379.         break;
  380.     case TK_ANCHOR_E:
  381.         x -= width;
  382.         y -= height/2;
  383.         break;
  384.     case TK_ANCHOR_SE:
  385.         x -= width;
  386.         y -= height;
  387.         break;
  388.     case TK_ANCHOR_S:
  389.         x -= width/2;
  390.         y -= height;
  391.         break;
  392.     case TK_ANCHOR_SW:
  393.         y -= height;
  394.         break;
  395.     case TK_ANCHOR_W:
  396.         y -= height/2;
  397.         break;
  398.     case TK_ANCHOR_NW:
  399.         break;
  400.     case TK_ANCHOR_CENTER:
  401.         x -= width/2;
  402.         y -= height/2;
  403.         break;
  404.     }
  405.  
  406.     /*
  407.      * Store the information in the item header.
  408.      */
  409.  
  410.     imgPtr->header.x1 = x;
  411.     imgPtr->header.y1 = y;
  412.     imgPtr->header.x2 = x + width;
  413.     imgPtr->header.y2 = y + height;
  414. }
  415.  
  416. /*
  417.  *--------------------------------------------------------------
  418.  *
  419.  * DisplayImage --
  420.  *
  421.  *    This procedure is invoked to draw a image item in a given
  422.  *    drawable.
  423.  *
  424.  * Results:
  425.  *    None.
  426.  *
  427.  * Side effects:
  428.  *    ItemPtr is drawn in drawable using the transformation
  429.  *    information in canvas.
  430.  *
  431.  *--------------------------------------------------------------
  432.  */
  433.  
  434. static void
  435. DisplayImage(canvas, itemPtr, display, drawable, x, y, width, height)
  436.     Tk_Canvas canvas;            /* Canvas that contains item. */
  437.     Tk_Item *itemPtr;            /* Item to be displayed. */
  438.     Display *display;            /* Display on which to draw item. */
  439.     Drawable drawable;            /* Pixmap or window in which to draw
  440.                      * item. */
  441.     int x, y, width, height;        /* Describes region of canvas that
  442.                      * must be redisplayed (not used). */
  443. {
  444.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  445.     short drawableX, drawableY;
  446.  
  447.     if (imgPtr->image == NULL) {
  448.     return;
  449.     }
  450.  
  451.     /*
  452.      * Translate the coordinates to those of the image, then redisplay it.
  453.      */
  454.  
  455.     Tk_CanvasDrawableCoords(canvas, (double) x, (double) y,
  456.         &drawableX, &drawableY);
  457.     Tk_RedrawImage(imgPtr->image, x - imgPtr->header.x1, y - imgPtr->header.y1,
  458.         width, height, drawable, drawableX, drawableY);
  459. }
  460.  
  461. /*
  462.  *--------------------------------------------------------------
  463.  *
  464.  * ImageToPoint --
  465.  *
  466.  *    Computes the distance from a given point to a given
  467.  *    rectangle, in canvas units.
  468.  *
  469.  * Results:
  470.  *    The return value is 0 if the point whose x and y coordinates
  471.  *    are coordPtr[0] and coordPtr[1] is inside the image.  If the
  472.  *    point isn't inside the image then the return value is the
  473.  *    distance from the point to the image.
  474.  *
  475.  * Side effects:
  476.  *    None.
  477.  *
  478.  *--------------------------------------------------------------
  479.  */
  480.  
  481. static double
  482. ImageToPoint(canvas, itemPtr, coordPtr)
  483.     Tk_Canvas canvas;        /* Canvas containing item. */
  484.     Tk_Item *itemPtr;        /* Item to check against point. */
  485.     double *coordPtr;        /* Pointer to x and y coordinates. */
  486. {
  487.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  488.     double x1, x2, y1, y2, xDiff, yDiff;
  489.  
  490.     x1 = imgPtr->header.x1;
  491.     y1 = imgPtr->header.y1;
  492.     x2 = imgPtr->header.x2;
  493.     y2 = imgPtr->header.y2;
  494.  
  495.     /*
  496.      * Point is outside rectangle.
  497.      */
  498.  
  499.     if (coordPtr[0] < x1) {
  500.     xDiff = x1 - coordPtr[0];
  501.     } else if (coordPtr[0] > x2)  {
  502.     xDiff = coordPtr[0] - x2;
  503.     } else {
  504.     xDiff = 0;
  505.     }
  506.  
  507.     if (coordPtr[1] < y1) {
  508.     yDiff = y1 - coordPtr[1];
  509.     } else if (coordPtr[1] > y2)  {
  510.     yDiff = coordPtr[1] - y2;
  511.     } else {
  512.     yDiff = 0;
  513.     }
  514.  
  515.     return hypot(xDiff, yDiff);
  516. }
  517.  
  518. /*
  519.  *--------------------------------------------------------------
  520.  *
  521.  * ImageToArea --
  522.  *
  523.  *    This procedure is called to determine whether an item
  524.  *    lies entirely inside, entirely outside, or overlapping
  525.  *    a given rectangle.
  526.  *
  527.  * Results:
  528.  *    -1 is returned if the item is entirely outside the area
  529.  *    given by rectPtr, 0 if it overlaps, and 1 if it is entirely
  530.  *    inside the given area.
  531.  *
  532.  * Side effects:
  533.  *    None.
  534.  *
  535.  *--------------------------------------------------------------
  536.  */
  537.  
  538. static int
  539. ImageToArea(canvas, itemPtr, rectPtr)
  540.     Tk_Canvas canvas;        /* Canvas containing item. */
  541.     Tk_Item *itemPtr;        /* Item to check against rectangle. */
  542.     double *rectPtr;        /* Pointer to array of four coordinates
  543.                  * (x1, y1, x2, y2) describing rectangular
  544.                  * area.  */
  545. {
  546.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  547.  
  548.     if ((rectPtr[2] <= imgPtr->header.x1)
  549.         || (rectPtr[0] >= imgPtr->header.x2)
  550.         || (rectPtr[3] <= imgPtr->header.y1)
  551.         || (rectPtr[1] >= imgPtr->header.y2)) {
  552.     return -1;
  553.     }
  554.     if ((rectPtr[0] <= imgPtr->header.x1)
  555.         && (rectPtr[1] <= imgPtr->header.y1)
  556.         && (rectPtr[2] >= imgPtr->header.x2)
  557.         && (rectPtr[3] >= imgPtr->header.y2)) {
  558.     return 1;
  559.     }
  560.     return 0;
  561. }
  562.  
  563. /*
  564.  *--------------------------------------------------------------
  565.  *
  566.  * ScaleImage --
  567.  *
  568.  *    This procedure is invoked to rescale an item.
  569.  *
  570.  * Results:
  571.  *    None.
  572.  *
  573.  * Side effects:
  574.  *    The item referred to by itemPtr is rescaled so that the
  575.  *    following transformation is applied to all point coordinates:
  576.  *        x' = originX + scaleX*(x-originX)
  577.  *        y' = originY + scaleY*(y-originY)
  578.  *
  579.  *--------------------------------------------------------------
  580.  */
  581.  
  582. static void
  583. ScaleImage(canvas, itemPtr, originX, originY, scaleX, scaleY)
  584.     Tk_Canvas canvas;            /* Canvas containing rectangle. */
  585.     Tk_Item *itemPtr;            /* Rectangle to be scaled. */
  586.     double originX, originY;        /* Origin about which to scale rect. */
  587.     double scaleX;            /* Amount to scale in X direction. */
  588.     double scaleY;            /* Amount to scale in Y direction. */
  589. {
  590.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  591.  
  592.     imgPtr->x = originX + scaleX*(imgPtr->x - originX);
  593.     imgPtr->y = originY + scaleY*(imgPtr->y - originY);
  594.     ComputeImageBbox(canvas, imgPtr);
  595. }
  596.  
  597. /*
  598.  *--------------------------------------------------------------
  599.  *
  600.  * TranslateImage --
  601.  *
  602.  *    This procedure is called to move an item by a given amount.
  603.  *
  604.  * Results:
  605.  *    None.
  606.  *
  607.  * Side effects:
  608.  *    The position of the item is offset by (xDelta, yDelta), and
  609.  *    the bounding box is updated in the generic part of the item
  610.  *    structure.
  611.  *
  612.  *--------------------------------------------------------------
  613.  */
  614.  
  615. static void
  616. TranslateImage(canvas, itemPtr, deltaX, deltaY)
  617.     Tk_Canvas canvas;            /* Canvas containing item. */
  618.     Tk_Item *itemPtr;            /* Item that is being moved. */
  619.     double deltaX, deltaY;        /* Amount by which item is to be
  620.                      * moved. */
  621. {
  622.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  623.  
  624.     imgPtr->x += deltaX;
  625.     imgPtr->y += deltaY;
  626.     ComputeImageBbox(canvas, imgPtr);
  627. }
  628.  
  629. /*
  630.  *----------------------------------------------------------------------
  631.  *
  632.  * ImageChangedProc --
  633.  *
  634.  *    This procedure is invoked by the image code whenever the manager
  635.  *    for an image does something that affects the image's size or
  636.  *    how it is displayed.
  637.  *
  638.  * Results:
  639.  *    None.
  640.  *
  641.  * Side effects:
  642.  *    Arranges for the canvas to get redisplayed.
  643.  *
  644.  *----------------------------------------------------------------------
  645.  */
  646.  
  647. static void
  648. ImageChangedProc(clientData, x, y, width, height, imgWidth, imgHeight)
  649.     ClientData clientData;        /* Pointer to canvas item for image. */
  650.     int x, y;                /* Upper left pixel (within image)
  651.                      * that must be redisplayed. */
  652.     int width, height;            /* Dimensions of area to redisplay
  653.                      * (may be <= 0). */
  654.     int imgWidth, imgHeight;        /* New dimensions of image. */
  655. {
  656.     ImageItem *imgPtr = (ImageItem *) clientData;
  657.  
  658.     /*
  659.      * If the image's size changed and it's not anchored at its
  660.      * northwest corner then just redisplay the entire area of the
  661.      * image.  This is a bit over-conservative, but we need to do
  662.      * something because a size change also means a position change.
  663.      */
  664.  
  665.     if (((imgPtr->header.x2 - imgPtr->header.x1) != imgWidth)
  666.         || ((imgPtr->header.y2 - imgPtr->header.y1) != imgHeight)) {
  667.     x = y = 0;
  668.     width = imgWidth;
  669.     height = imgHeight;
  670.     Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1,
  671.         imgPtr->header.y1, imgPtr->header.x2, imgPtr->header.y2);
  672.     } 
  673.     ComputeImageBbox(imgPtr->canvas, imgPtr);
  674.     Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1 + x,
  675.         imgPtr->header.y1 + y, (int) (imgPtr->header.x1 + x + width),
  676.         (int) (imgPtr->header.y1 + y + height));
  677. }
  678.